package com.generate;


import cn.hutool.core.util.CharsetUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
import java.util.Collection;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class SignUtil {

    private final static String PARAM_SIGN = "signature";
    private static final String KEY_ALGORITHM = "SHA1withRSA";
    private static Signature signature;

    static {
        try {
            signature = Signature.getInstance(KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取签名
     *
     * @param data
     * @param privateKey
     * @return
     */
    public static String sign(byte[] data, PrivateKey privateKey) {
        try {
            signature.initSign(privateKey);
            signature.update(data);
            return new String(Base64.getEncoder().encode(signature.sign()), CharsetUtil.UTF_8);
        } catch (InvalidKeyException | SignatureException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String sign(Object data, PrivateKey privateKey) {
        return sign(getParams(data), privateKey);
    }

    /**
     * 验签
     *
     * @param data
     * @param sign
     * @param publicKey
     * @return
     */
    public static boolean verify(byte[] data, byte[] sign, PublicKey publicKey) {
        try {
            signature.initVerify(publicKey);
            signature.update(data);
            return signature.verify(Base64.getDecoder().decode(sign));
        } catch (InvalidKeyException | SignatureException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static boolean verify(Object data, String signature, PublicKey publicKey) {
        return verify(getParams(data), signature.getBytes(StandardCharsets.UTF_8), publicKey);
    }

    /**
     * 获取参数
     *
     * @param obj
     * @return
     */
    public static byte[] getParams(Object obj) {
        if (Objects.isNull(obj)) {
            log.error("签名获取失败, 传入对象为null");
            return null;
        }
        // 获取非sign参数值
        JSONObject js = JSONObject.parseObject(JSONObject.toJSONString(obj));
        js.remove(PARAM_SIGN);

        Collection<Object> values = js.values();
        String params = values.stream().map(String::valueOf).sorted().collect(Collectors.joining());
        System.out.println("加密前：=" + params);
        return params.getBytes(StandardCharsets.UTF_8);
    }

}

